package DTask::Cache;
use 5.018;
use warnings;

my ($cache_db);

use DTask::Utils qw(wrapMangoOp);
use Carp qw(carp);
use Data::Dumper;

sub setMango
{
	my $mango = shift;
	$cache_db = $mango->db('dtask_cache');
}

sub getLinkInfo
{
	my ($target, $target_id, $delay, $cb) = @_;
	getLinksInfoFromCache($target, $target_id, sub {
		my ($info) = @_;
		my $result;
		if ($info->{error})
		{
			warn "getLinkInfo: failed get $target $target_id info";
			$result = "failed get $target $target_id";
		}
		else
		{
			warn "getLinkInfo: get $target $target_id info is $info->{info}";
			$result = "$target $target_id " . $info->{info};
		}
		$delay->pass($result);
		$cb->();
	});
}

sub getLinksInfoFromCache
{
	my ($target, $target_id, $cb) = @_;
	warn "getLinksInfoFromCache $target $target_id";

	my $collection = $cache_db->collection($target);
	$collection->find_one({_id => $target_id }, {_id => 0}, sub {
		my $doc = wrapMangoOp(@_);
		if ($doc)
		{
			warn "getLinksInfoFromCache dump \$doc";
			warn Dumper $doc;
			$cb->($doc);
		}
		else
		{
			getLinkInfoFromOriginal($target, $target_id, sub {
				my ($ret) = @_;
				unless ($ret->{error})
				{
					cache($target, $target_id, $ret->{info}, sub {
						warn "cache done";
						$cb->($ret);
					});

				}
				else
				{
					warn "getLinkInfoFromOriginal error";
					cache($target, $target_id, undef, sub {
						warn "remove old cache";
						$cb->($ret);
					})
				}
			});
		}
	});
}

sub cache
{
	my ($target, $target_id, $info, $cb) = @_;
	my $collection = $cache_db->collection($target);

	if ( defined $info )
	{
		$collection->update({_id => $target_id }, {'$set' => {info => $info} }, sub {
			my $doc = wrapMangoOp(@_);		
			if ( $doc->{ok} && $doc->{n} > 0 )
			{
				warn "cache: $target has $target_id, update";
				$cb->();
			}
			else
			{
				warn "cache: $target has not $target_id, insert";
				$collection->insert({_id => $target_id , info => $info }, sub {
					wrapMangoOp(@_);	
					$cb->();
				});
			}
		});

	}
	else
	{
		#remove old cache
		warn "cache: $target $target_id on error remove old cache";
		$collection->remove({_id => $target_id}, sub {
			my $doc = wrapMangoOp(@_);	
			warn "dump remove \$doc";
			warn Dumper $doc;
			$cb->();
		});
	}
}

sub getLinkInfoFromOriginal
{
	my ($target, $target_id, $cb) = @_;
	warn "getLinkInfoFromOriginal $target $target_id";

	$target =~ s/^(\w)/\U$1/;
	$target =~ s/_(\w)/\U$1/g;

	eval "use ${target}::Query";
	warn $@ if $@;

	my $result;
	my $get_sub = \&{ $target . "::Query::getInfo" };

	eval { $get_sub->($target_id,$cb) };
	if ($@)
	{
		warn "undefined $@";
		$cb->({error => 1});
	}

}

1;
